-- 灰度发布 Lua 脚本（需要 OpenResty）
-- 用于 Nginx 根据用户ID查询 Redis 灰度白名单并路由到对应版本

local redis = require "resty.redis"
local cjson = require "cjson"
local jwt = require "resty.jwt"

-- Redis 配置
local redis_host = "127.0.0.1"  -- Redis 主机地址
local redis_port = 6379          -- Redis 端口
local redis_password = nil       -- Redis 密码（如果有）
local redis_timeout = 1000       -- Redis 连接超时（毫秒）

-- CDN 基础地址
local cdn_base = "https://mybox-1257251314.cos.ap-chengdu.myqcloud.com/www/micro-frontend"
local base_app_id = "vue-base"

-- 从 Token 中解析用户ID
local function get_user_id_from_token(token)
    if not token or token == "" then
        return nil
    end
    
    -- 移除 Bearer 前缀
    token = string.gsub(token, "^Bearer%s+", "")
    
    -- 解析 JWT Token
    local jwt_obj = jwt:verify("your-secret-key", token)  -- 注意：这里需要实际的密钥
    if not jwt_obj or not jwt_obj.valid then
        return nil
    end
    
    -- 从 payload 中获取 userId
    local payload = jwt_obj.payload
    return payload.userId or payload.user_id or nil
end

-- 查询 Redis 获取用户的灰度版本
local function get_gray_version(app_id, user_id)
    if not user_id or user_id == "" then
        return nil
    end
    
    local red = redis:new()
    red:set_timeout(redis_timeout)
    
    local ok, err = red:connect(redis_host, redis_port)
    if not ok then
        ngx.log(ngx.ERR, "failed to connect to redis: ", err)
        return nil
    end
    
    -- 如果有密码，进行认证
    if redis_password then
        local auth_ok, auth_err = red:auth(redis_password)
        if not auth_ok then
            ngx.log(ngx.ERR, "failed to authenticate redis: ", auth_err)
            red:close()
            return nil
        end
    end
    
    -- 查询灰度版本
    local redis_key = "gray:user:version:" .. app_id
    local version, err = red:hget(redis_key, user_id)
    
    -- 关闭连接
    red:close()
    
    if err then
        ngx.log(ngx.ERR, "failed to get gray version from redis: ", err)
        return nil
    end
    
    return version
end

-- 构建 CDN 路径
local function build_cdn_path(app_id, version, is_gray)
    if is_gray and version then
        -- 灰度版本路径：{app_id}/{version}/index.html
        return cdn_base .. "/" .. app_id .. "/" .. version .. "/index.html"
    else
        -- 生产版本路径：{app_id}/index.html
        return cdn_base .. "/" .. app_id .. "/index.html"
    end
end

-- 主处理函数
local function handle_gray_release()
    -- 获取 Authorization header
    local auth_header = ngx.var.http_authorization
    if not auth_header then
        -- 没有 Token，返回生产版本
        return build_cdn_path(base_app_id, nil, false)
    end
    
    -- 从 Token 中提取用户ID
    local user_id = get_user_id_from_token(auth_header)
    if not user_id then
        -- 无法解析用户ID，返回生产版本
        return build_cdn_path(base_app_id, nil, false)
    end
    
    -- 查询灰度版本
    local gray_version = get_gray_version(base_app_id, user_id)
    if gray_version and gray_version ~= ngx.null then
        -- 有灰度版本，返回灰度路径
        return build_cdn_path(base_app_id, gray_version, true)
    else
        -- 没有灰度版本，返回生产版本
        return build_cdn_path(base_app_id, nil, false)
    end
end

-- 执行并返回结果
local cdn_path = handle_gray_release()
ngx.var.gray_cdn_path = cdn_path

